package com.kzj.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.kzj.common.MyUserPhoneThreadLocal;
import com.kzj.common.constant.GlobalConstant;
import com.kzj.common.exception.MyException;
import com.kzj.common.re.Result;
import com.kzj.dao.EquationDao;
import com.kzj.dao.UserDao;
import com.kzj.domain.Equation;
import com.kzj.domain.Exercises;
import com.kzj.dao.ExercisesDao;
import com.kzj.domain.User;
import com.kzj.domain.bp.ExercisesBP;
import com.kzj.domain.dto.EquationDTO;
import com.kzj.domain.dto.ExercisesDTO;
import com.kzj.domain.vo.EquationVO;
import com.kzj.service.EquationService;
import com.kzj.service.ExercisesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author kzj
 * @since 2023-11-15
 */
@Service
public class ExercisesServiceImpl extends ServiceImpl<ExercisesDao, Exercises> implements ExercisesService {
    @Autowired
    EquationService equationService;
    @Autowired
    EquationDao equationDao;
    @Autowired
    UserDao userDao;

    @Override
    @Transactional
    public Result create(ExercisesDTO exercisesDTO) {
        if (exercisesDTO.getCreateType()==null)
        {
            exercisesDTO.setCreateType(Exercises.ONLINE);
        }
        if(exercisesDTO.getNumber()<=0)
        {
            return Result.error(GlobalConstant.EXERCISES_NUMBER_ERROR);
        }
        String userPhone = MyUserPhoneThreadLocal.getUserPhone();
        User user = userDao.selectById(userPhone);
        long exerciseId = IdWorker.getId();
        List<Equation> equationList = new ExercisesBP(exercisesDTO.getNumber(), exercisesDTO.getType(),user.getGrade()).getEquationList(exerciseId);
        Exercises exercises = new Exercises();
        exercises.setId(exerciseId);
        exercises.setUserPhone(userPhone);
        exercises.setCreateTime(LocalDateTime.now());
        BeanUtils.copyProperties(exercisesDTO,exercises);
        equationService.saveBatch(equationList);
        this.save(exercises);
        List<EquationVO> collect = equationList.stream().map(item -> getEquationVO(item)).collect(Collectors.toList());
        return Result.success(collect);
    }
    @Transactional
    @Override
    public Result check(List<EquationDTO> equationDTOList,Integer practiceTime) {
        if(equationDTOList==null||equationDTOList.isEmpty())
        {
            return Result.error(GlobalConstant.EXERCISES_NUMBER_ERROR);
        }
        for (EquationDTO equationDTO : equationDTOList) {
            equationService.update().setSql("practice_correctly = "+equationDTO.getPracticeCorrectly()).eq("id",equationDTO.getId()).update();
        }
        if(practiceTime!=null)
        {
            EquationDTO equationDTO = equationDTOList.get(0);
            LambdaQueryWrapper<Equation> lqw = new LambdaQueryWrapper<>();
            lqw.eq(Equation::getId, equationDTO.getId());
            Equation equation = equationService.getOne(lqw);
            this.update().setSql("practice_time = "+practiceTime).eq("id",equation.getExercisesId()).update();
        }
        return Result.success();
    }
    @Transactional
    @Override
    public Result exportDocument(ExercisesDTO exercisesDTO, HttpServletResponse response) {
        exercisesDTO.setCreateType(Exercises.DOCUMENT);
        //判断题目的数量是否在限定范围内
        if(exercisesDTO.getNumber()>GlobalConstant.EXCEL_CREATE_EQUATION_UP||exercisesDTO.getNumber()<=0)
        {
            throw new MyException(GlobalConstant.EXCEL_CREATE_EQUATION_OVER_UP);
        }
        XSSFWorkbook excel= null;
        try {
            //读入模版文件
            excel = new XSSFWorkbook(new ClassPathResource(GlobalConstant.EXCEL_TEMPLATE_PATH).getInputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //获取用户信息
        String userPhone = MyUserPhoneThreadLocal.getUserPhone();
        //将数据写入文件
        DateTimeFormatter format=DateTimeFormatter.ofPattern("yyyy年MM月dd日");
        XSSFSheet sheet = excel.getSheetAt(0);
        sheet.getRow(1).getCell(4).setCellValue(userPhone);
        sheet.getRow(3).getCell(2).setCellValue(LocalDateTime.now().format(format));
        sheet.getRow(3).getCell(4).setCellValue(ExercisesBP.getTypeToString(exercisesDTO.getType()));
        sheet.getRow(3).getCell(6).setCellValue(exercisesDTO.getNumber());
        ExercisesService proxy = (ExercisesService)AopContext.currentProxy();
        Result result = null;
        if(exercisesDTO.getType().equals(Exercises.ERROR_SET))
        {
            result=proxy.errorSet(exercisesDTO);
        }
        else
        {
            result=proxy.create(exercisesDTO);
        }
        List<EquationVO> data = (List<EquationVO>)result.getData();
        for (int i = 0; i < data.size(); i++) {
            XSSFRow row = sheet.getRow(6 + i);
            System.out.println(row);
            System.out.println(row.getCell(0));
            row.getCell(1).setCellValue(i+1);
            row.getCell(3).setCellValue(data.get(i).getContent());
        }
        try {
            excel.write(response.getOutputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        finally {
            try {
                excel.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return Result.success();
    }

    @Override
    public Result errorSet(ExercisesDTO exercisesDTO) {
        String userPhone = MyUserPhoneThreadLocal.getUserPhone();
        List<Equation> equationList=equationDao.getFalseByUserPhone(userPhone);
        Collections.shuffle(equationList);
        Integer len= Math.min(equationList.size(),exercisesDTO.getNumber());
        List<Equation> equationList1 = equationList.subList(0, len);
        List<EquationVO> collect = equationList1.stream().map(item ->getEquationVO(item)).collect(Collectors.toList());
        return Result.success(collect);
    }
    private EquationVO getEquationVO(Equation equation)
    {
        EquationVO equationVO = new EquationVO();
        BeanUtils.copyProperties(equation, equationVO);
        return equationVO;
    }
}
